home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / ODF Release 3 / ODFDev / Clock / Sources / Part.cpp < prev    next >
Encoding:
Text File  |  1996-12-16  |  13.8 KB  |  482 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                Part.cpp
  4. //    Release Version:    $ ODF 3 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #ifndef PART_H
  11. #include "Part.h"
  12. #endif
  13.  
  14. #ifndef DEFINES_K
  15. #include "Defines.k"
  16. #endif
  17.  
  18. #ifndef BINDING_K
  19. #include "Binding.k"
  20. #endif
  21.  
  22. #ifndef FRAME_H
  23. #include "Frame.h"
  24. #endif
  25.  
  26. #ifndef CONTENT_H
  27. #include "Content.h"
  28. #endif
  29.  
  30. #ifndef VIEW_H
  31. #include "View.h"
  32. #endif
  33.  
  34. #ifndef DIALOG_H
  35. #include "Dialog.h"
  36. #endif
  37.  
  38. // ----- Framework Layer -----
  39.  
  40. #ifndef FWPRTITE_H
  41. #include "FWPrtIte.h"
  42. #endif
  43.  
  44. #ifndef FWABOUT_H
  45. #include "FWAbout.h"
  46. #endif
  47.  
  48. #ifndef FWITERS_H
  49. #include "FWIters.h"
  50. #endif
  51.  
  52. #ifndef FWIDLE_H
  53. #include "FWIdle.h"
  54. #endif
  55.  
  56. // ----- OS Layer -----
  57.  
  58. #ifndef FWMENU_H
  59. #include "FWMenu.h"
  60. #endif
  61.  
  62. #ifndef FWODMISC_H
  63. #include "FWODMisc.h"
  64. #endif
  65.  
  66. #ifndef FWEVENT_H
  67. #include "FWEvent.h"
  68. #endif
  69.  
  70. #ifndef FWCFMRES_H
  71. #include "FWCFMRes.h"
  72. #endif
  73.  
  74. #ifndef FWRESTYP_H
  75. #include "FWResTyp.h"
  76. #endif
  77.  
  78. // ----- Foundation Layer -----
  79.  
  80. #ifndef FWMEMMGR_H
  81. #include "FWMemMgr.h"
  82. #endif
  83.  
  84. // ----- OpenDoc Includes -----
  85.  
  86. #ifndef SOM_Module_OpenDoc_StdProps_defined
  87. #include <StdProps.xh>
  88. #endif
  89.  
  90. // ----- Macintosh Includes -----
  91.  
  92. #if defined(FW_BUILD_MAC) && !defined(__SOUND__)
  93. #include <Sound.h>
  94. #endif
  95.  
  96. //========================================================================================
  97. // Runtime information
  98. //========================================================================================
  99.  
  100. #ifdef FW_BUILD_MAC
  101. #pragma segment odfclock
  102. #endif
  103.  
  104. //========================================================================================
  105. //    Globals
  106. //========================================================================================
  107.  
  108. //========================================================================================
  109. // Constants
  110. //========================================================================================
  111.  
  112. const short kClockIdleFreq = 15;
  113.  
  114. //========================================================================================
  115. //    Class CClockPart
  116. //========================================================================================
  117.  
  118. FW_DEFINE_AUTO(CClockPart)
  119.     
  120. //----------------------------------------------------------------------------------------
  121. // CClockPart::CClockPart
  122. //----------------------------------------------------------------------------------------
  123. CClockPart::CClockPart(ODPart* odPart) :
  124.     FW_CPart(odPart, FW_gInstance, kPartInfoID),
  125.     fLastTime(FW_CTime::GetCurrentTime()),
  126.     fClockContent(NULL),
  127.     fLockIdle(FALSE),
  128.     fIdler(NULL),
  129.     fUsesAnalog(TRUE),
  130. #ifdef FW_BUILD_MAC
  131.     fChimeSound(NULL),
  132.     fTickSound(NULL)
  133. #endif
  134. {
  135.     FW_END_CONSTRUCTOR
  136. }
  137.  
  138. //----------------------------------------------------------------------------------------
  139. // CClockPart::~CClockPart
  140. //----------------------------------------------------------------------------------------
  141. CClockPart::~CClockPart()
  142. {
  143.     FW_START_DESTRUCTOR
  144.     
  145.     delete fIdler;
  146.     
  147. #ifdef FW_BUILD_MAC
  148.     if (fChimeSound)
  149.         FW_CMemoryManager::FreeSystemHandle((FW_PlatformHandle)fChimeSound);
  150.     fChimeSound = NULL;
  151.  
  152.     if (fTickSound)
  153.         FW_CMemoryManager::FreeSystemHandle((FW_PlatformHandle)fTickSound);
  154.     fTickSound = NULL;
  155. #endif
  156. }
  157.  
  158. //----------------------------------------------------------------------------------------
  159. // CClockPart::Initialize
  160. //----------------------------------------------------------------------------------------
  161.  
  162. void CClockPart::Initialize(Environment* ev, ODStorageUnit* storageUnit, FW_Boolean fromStorage)
  163. {
  164.     FW_CPart::Initialize(ev, storageUnit, fromStorage);
  165.     
  166.     // ----- Register Presentation -----
  167.     fAnalogPresentation = RegisterPresentation(ev, kAnalogPresentation, TRUE, kAnalogClockView, kAnalogClockViewRoot);
  168.     fDigitalPresentation = RegisterPresentation(ev, kDigitalPresentation, FALSE, kDigitalClockView, kDigitalClockViewRoot);
  169.     fClockSettingsPresentation = RegisterPresentation(ev, kClockSettingsPresentation, false, kClockSettingsDialog, kClockSettingsDialog);
  170.             
  171.     // We instantiate a FW_CToggleItem from a stream so we must 
  172.     // keep it from being deadstripped.
  173.     FW_DO_NOT_DEAD_STRIP(FW_CToggleItem);
  174.  
  175. #ifdef FW_BUILD_MAC    
  176.     FW_PSharedLibraryResourceFile resFile(ev);
  177.     
  178.     // ----- Get default clock sounds
  179.     fChimeSound = ::GetResource(soundListRsrc, kClockChime);
  180.     ::DetachResource(fChimeSound);
  181.     
  182.     fTickSound = ::GetResource(soundListRsrc, kClockTick);
  183.     ::DetachResource(fTickSound);
  184. #endif
  185.  
  186.     // ----- Create the Idler -----
  187.     fIdler = FW_NEW(FW_CIdler, (this, kClockIdleFreq));
  188.     fIdler->RegisterIdle(ev);
  189. }
  190.  
  191. //------------------------------------------------------------------------------
  192. // CClockPart::NewPartContent
  193. //------------------------------------------------------------------------------
  194.  
  195. FW_CContent* CClockPart::NewPartContent(Environment* ev)
  196. {
  197.     fClockContent = FW_NEW(CClockContent, (ev, this));
  198.     return fClockContent;
  199. }
  200.  
  201. //----------------------------------------------------------------------------------------
  202. // CClockPart::NewFrame
  203. //----------------------------------------------------------------------------------------
  204.  
  205. FW_CFrame* CClockPart::NewFrame(Environment* ev, ODFrame* odFrame, FW_CPresentation* presentation, FW_Boolean fromStorage)
  206. {
  207.     FW_UNUSED(fromStorage);
  208.  
  209.     if (presentation == fClockSettingsPresentation)
  210.     {
  211.         return FW_NEW(CClockSettingsDialogFrame, (ev, odFrame, presentation, this));
  212.     }
  213.  
  214.     fUsesAnalog = presentation == fAnalogPresentation;
  215.     
  216.     return FW_NEW(CClockFrame, (ev, odFrame, presentation, this, fClockContent));
  217. }
  218.  
  219. //----------------------------------------------------------------------------------------
  220. // CClockPart::Tick
  221. //----------------------------------------------------------------------------------------
  222.  
  223. short CClockPart::Tick(Environment* ev, FW_CPresentation* presentation, const FW_CTime& currentTime)
  224. {
  225.     short frameCount = 0;
  226.         
  227.     // Update all the display frames of the same type
  228.     FW_CPresentationFrameIterator iter(ev, presentation);
  229.     for (CClockFrame *clockFrame = (CClockFrame*)iter.First(ev); iter.IsNotComplete(ev); clockFrame = (CClockFrame*)iter.Next(ev))
  230.     {
  231.         if ((!clockFrame->IsInLimbo(ev)))
  232.         {
  233.             frameCount++;
  234.             if (clockFrame->GetViewType(ev) == FW_CPart::fgViewAsFrameToken)
  235.             {
  236.                 CClockView* clockView = clockFrame->GetClockView(ev);
  237.                 if (clockView)
  238.                     clockView->UpdateClock(ev, currentTime);
  239.             }
  240.         }
  241.     }
  242.     
  243.     return frameCount;
  244. }
  245.  
  246. //----------------------------------------------------------------------------------------
  247. // CClockPart::DoIdle
  248. //----------------------------------------------------------------------------------------
  249.  
  250. FW_Handled CClockPart::DoIdle(Environment* ev, const FW_CNullEvent& theNullEvent)
  251. {
  252.     FW_UNUSED(theNullEvent);
  253.  
  254.     if (fLockIdle)
  255.         return FW_kHandled;
  256.         
  257.     FW_CTime currentTime = FW_CTime::GetCurrentTime() + fClockContent->GetTimeOffset();
  258.      if (fLastTime != currentTime)
  259.     {
  260.         short frameCount = 0;
  261.         
  262.         frameCount = Tick(ev, fAnalogPresentation, currentTime);    
  263.         frameCount += Tick(ev, fDigitalPresentation, currentTime);
  264.         
  265.         if (frameCount > 0)
  266.         {
  267.             if (fClockContent->HasTickSound())
  268.                 this->PlayTickSound();
  269.             if (fClockContent->HasChimeSound() && (currentTime.GetMinute() == 0) && (currentTime.GetSecond() == 0))
  270.                 this->PlayChimeSound();
  271.         }
  272.         
  273.         fLastTime = currentTime;
  274.     }
  275.     return FW_kHandled;
  276. }
  277.  
  278. //----------------------------------------------------------------------------------------
  279. // CClockPart::DoAbout
  280. //----------------------------------------------------------------------------------------
  281.  
  282. FW_Handled CClockPart::DoAbout(Environment* ev)
  283. {
  284.     ::FW_About(ev, this, kAbout);
  285.     
  286.     return FW_kHandled;
  287. }
  288.  
  289. //----------------------------------------------------------------------------------------
  290. // CClockPart::SynchContainingPartProperties
  291. //----------------------------------------------------------------------------------------
  292.  
  293. void CClockPart::SynchContainingPartProperties(Environment* ev, FW_CPresentation* presentation)
  294. {
  295.     FW_CPresentationFrameIterator iter(ev, presentation);
  296.     for (CClockFrame* frame = (CClockFrame*)iter.First(ev); iter.IsNotComplete(ev); frame = (CClockFrame*)iter.Next(ev))
  297.     {
  298.         frame->SynchContainingPartProperties(ev);
  299.     }
  300. }
  301.  
  302. //----------------------------------------------------------------------------------------
  303. // CClockPart::DoMenu
  304. //----------------------------------------------------------------------------------------
  305.  
  306. FW_Handled CClockPart::DoMenu(Environment* ev, const FW_CMenuEvent& theMenuEvent)
  307. {
  308.     FW_Handled menuHandled = FW_kHandled;
  309.     
  310.     switch (theMenuEvent.GetCommandID(ev))
  311.     {
  312.         case cClockSoundsTick:
  313.             fClockContent->ToggleTickSound();
  314.             this->Changed(ev);
  315.             break;
  316.  
  317.         case cClockSoundsChime:
  318.             fClockContent->ToggleChimeSound();
  319.             this->Changed(ev);
  320.             break;
  321.                 
  322.         case cClockSettings:
  323.             OpenClockSettingsDialog(ev);
  324.             break;
  325.  
  326.         case cClockUseContainerColor:
  327.             {
  328.                 fClockContent->ToggleUsesContainerColor();
  329.                 this->Changed(ev);
  330.                 
  331.                 SynchContainingPartProperties(ev, fAnalogPresentation);
  332.                 SynchContainingPartProperties(ev, fDigitalPresentation);
  333.             }
  334.             break;
  335.  
  336.         case cClockType:
  337.             {
  338.                 UseAnalogPresentation(ev, !UsesAnalogPresentation(ev));
  339.             }
  340.             break;
  341.  
  342.         default:
  343.             menuHandled = FW_kNotHandled;
  344.     }            
  345.     
  346.     return menuHandled;
  347. }
  348.  
  349. //----------------------------------------------------------------------------------------
  350. // CClockPart::DoAdjustMenus
  351. //----------------------------------------------------------------------------------------
  352.  
  353. FW_Handled CClockPart::DoAdjustMenus(Environment* ev, FW_CMenuBar* menuBar, FW_Boolean hasMenuFocus, FW_Boolean isRoot)
  354. {
  355.     if (hasMenuFocus)
  356.     {    
  357.         menuBar->EnableAndCheckCommand(ev, cClockSoundsTick, TRUE, fClockContent->HasTickSound());
  358.         menuBar->EnableAndCheckCommand(ev, cClockSoundsChime, TRUE, fClockContent->HasChimeSound());
  359.  
  360.         // Find out if the Clock Settings dialog is active 
  361.         FW_Boolean isDialogActive = false;
  362.         FW_CFrame* activeFrame = this->GetLastActiveFrame(ev);
  363.         if (activeFrame && activeFrame->GetPresentation(ev) == fClockSettingsPresentation)
  364.             isDialogActive = true;
  365.  
  366.         // Don't enable the Clock Settings menu item if the dialog is already open
  367.         menuBar->EnableCommand(ev, cClockSettings, !isDialogActive);
  368.  
  369.         menuBar->EnableAndCheckCommand(ev, cClockUseContainerColor, !isRoot, fClockContent->UsesContainerColor());
  370.  
  371.         menuBar->EnableAndToggleCommand(ev, cClockType, TRUE, !UsesAnalogPresentation(ev));    
  372.     }
  373.         
  374.     return FW_kNotHandled;
  375. }
  376.  
  377. //----------------------------------------------------------------------------------------
  378. // CClockPart::PlayTickSound
  379. //----------------------------------------------------------------------------------------
  380.  
  381. void CClockPart::PlayTickSound()
  382. {
  383. #ifdef FW_BUILD_MAC
  384.     ::SndPlay(NULL, (SndListHandle)fTickSound, TRUE);
  385. #endif
  386. #ifdef FW_BUILD_WIN
  387.     ::MessageBeep(-1);
  388. #endif
  389. }
  390.  
  391. //----------------------------------------------------------------------------------------
  392. // CClockPart::PlayChimeSound
  393. //----------------------------------------------------------------------------------------
  394.  
  395. void CClockPart::PlayChimeSound()
  396. {
  397. #ifdef FW_BUILD_MAC
  398.     ::SndPlay(NULL, (SndListHandle)fChimeSound, TRUE);
  399. #endif
  400. #ifdef FW_BUILD_WIN
  401.     ::MessageBeep(-1);
  402. #endif
  403. }
  404.  
  405. //----------------------------------------------------------------------------------------
  406. // CClockPart::UseAnalogPresentation
  407. //----------------------------------------------------------------------------------------
  408.  
  409. void CClockPart::UseAnalogPresentation(Environment* ev, FW_Boolean analog)
  410. {    
  411.     if(fUsesAnalog != analog)
  412.     {
  413.         FW_CPresentation* oldPresentation = fUsesAnalog ? fAnalogPresentation : fDigitalPresentation;
  414.  
  415.         FW_CPresentation* newPresentation = fUsesAnalog ? fDigitalPresentation : fAnalogPresentation;
  416.         
  417.         oldPresentation->ChangeAllFramesPresentation(ev, newPresentation);
  418.  
  419.         newPresentation->ContentUpdated(ev);
  420.         
  421.         Changed(ev);    // document has changed (enable Save menu item)
  422.  
  423.         fUsesAnalog = analog;
  424.     }
  425. }
  426.  
  427. //----------------------------------------------------------------------------------------
  428. // CClockPart::UsesAnalogPresentation
  429. //----------------------------------------------------------------------------------------
  430.  
  431. FW_Boolean CClockPart::UsesAnalogPresentation(Environment* ev) const
  432. {
  433. FW_UNUSED(ev);
  434.     return fUsesAnalog;
  435. }
  436.  
  437. //----------------------------------------------------------------------------------------
  438. // CClockPart::OpenClockSettingsDialog
  439. //----------------------------------------------------------------------------------------
  440.  
  441. void CClockPart::OpenClockSettingsDialog(Environment* ev)
  442. {
  443.     FW_CPoint position(FW_kZeroPoint);
  444.     FW_CPoint size(FW_IntToFixed(320), FW_IntToFixed(130));
  445.     FW_WindowStyle style = FW_kStandardDialogPosition | FW_kHasCaption;
  446.  
  447.     FW_CString title;
  448.     FW_PSharedLibraryResourceFile resFile(ev);
  449.     ::FW_LoadStringByID(ev, resFile, kClockStrings, FW_kMultiStringRes, kClockSettingsTitleString, title);
  450.  
  451.     CClockSettingsDialogFrame* dialog = (CClockSettingsDialogFrame*) FW_CDialogFrame::NewAndShowModalDialog(ev, 
  452.                             this,                        // Your part
  453.                             fClockSettingsPresentation, // Used in NewFrame
  454.                             size,                         // Window size
  455.                             position,                     // Window position
  456.                             style,                        // Make dialog moveable
  457.                             title);                        // Title for moveable dialog
  458. }
  459.  
  460. //----------------------------------------------------------------------------------------
  461. // CClockPart::SetClock
  462. //----------------------------------------------------------------------------------------
  463.  
  464. void CClockPart::SetClock(Environment* ev, long hourOffset, const FW_CString& faceString)
  465. {
  466.     // FW_CTimeSpan(long days, short hours, short minutes, short seconds);
  467.     FW_CTimeSpan offset(0, hourOffset, 0, 0);
  468.     fClockContent->SetTimeOffset(offset);
  469.     fClockContent->SetFaceString(faceString);
  470.  
  471.     // Notify interested parties of change
  472.     this->Changed(ev);
  473.     fAnalogPresentation->ContentUpdated(ev);
  474.     fDigitalPresentation->ContentUpdated(ev);
  475.  
  476.     // Redraw the analog clock
  477.     fAnalogPresentation->Invalidate(ev);
  478.  
  479.     // Don't need to redraw the digital clock since it will update in a second
  480. //    fDigitalPresentation->Invalidate(ev);
  481. }
  482.